﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WordNet.Core;
using WordNet.Core.Graph;

namespace GraphTest
{
    [TestClass]
    public class DigraphTest
    {
        public static int[][] dgCycle = new int[][] {new[]{4,2},new[]{2,3}, new[] {3,2},new[] {6,0}, new[]{0,1}, new[]{2,0}, new[]{11,12},
        new[] {12,9},new[] {9,10},new[] {9,11},new[]{8,9}, new[]{10,12},new[]{11,4},new[] {4,3},
                            new[]{3,5}, new[]{7,8},new[]{8,7},new[]{5,4},new[]{0,5},new[]{6,4},new[]{6,9},new[]{7,6}};

        public static int[][] dgNoCycle = new int[][]{ new[]{2,3},new[]{0,6},new[]{0,1},new[]{2,0},new[]{11,12},new[]{9,12},new[]{9,11},new[]{9, 10},
                                  new[]{3,5}, new[]{8,7}, new[]{5,4}, new[]{0,5}, new[]{6,4}, new[]{6,9}, new[]{7,6} };
        [TestMethod]
        public void CanCreateDigraphTest()
        {
            Digraph g = new Digraph(dgCycle.Length);
            for (int i = 0; i < dgCycle.Length; i++)
            {
                g.AddEdge(dgCycle[i][0], dgCycle[i][1]);
            }
            Assert.AreEqual(13, g.NumberOfVertices);
            Assert.AreEqual(dgCycle.Length, g.NumberOfEdges);
        }

        [TestMethod]
        public void CanFindCycle()
        {
            Digraph g = new Digraph(dgCycle.Length);
            for (int i = 0; i < dgCycle.Length; i++)
            {
                g.AddEdge(dgCycle[i][0], dgCycle[i][1]);
            }
            DirectedCycle cycle = new DirectedCycle(g);
            Assert.IsTrue(cycle.HasCycle);
        }

        [TestMethod]
        public void CanFindNoCycle()
        {
            Digraph g = new Digraph(dgNoCycle.Length);
            for (int i = 0; i < dgNoCycle.Length; i++)
            {
                g.AddEdge(dgNoCycle[i][0], dgNoCycle[i][1]);
            }
            DirectedCycle cycle = new DirectedCycle(g);
            Assert.IsFalse(cycle.HasCycle);

        }

        [TestMethod]
        public void CanFindShortestPath()
        {
            Digraph g = new Digraph(dgNoCycle.Length);
            for (int i = 0; i < dgNoCycle.Length; i++)
            {
                g.AddEdge(dgNoCycle[i][0], dgNoCycle[i][1]);
            }
            DirectedShortestPath shortestPath = new DirectedShortestPath(g, 0);
            // 0 -> 6 -> 9 -> 12
            Assert.AreEqual(3, shortestPath.DistanceTo(12));
            // 0 -> 6 -> 9 -> 11 -> 12
            Assert.AreNotEqual(4, shortestPath.DistanceTo(12));
        }

        [TestMethod]
        public void CanFindShortestPathCycleGraph()
        {
            Digraph g = new Digraph(dgCycle.Length);
            for (int i = 0; i < dgCycle.Length; i++)
            {
                g.AddEdge(dgCycle[i][0], dgCycle[i][1]);
            }
            DirectedShortestPath shortestPath = new DirectedShortestPath(g, 6);
            Assert.AreEqual(3, shortestPath.DistanceTo(12));
            Assert.AreEqual(1, shortestPath.DistanceTo(4));
            Assert.AreEqual(2, shortestPath.DistanceTo(5));
            // no connection
            Assert.AreEqual(int.MaxValue, shortestPath.DistanceTo(7));
        }
        
        [TestMethod]
        public void CanShowShortestPath()
        {
            Digraph g = new Digraph(dgNoCycle.Length);
            for (int i = 0; i < dgNoCycle.Length; i++)
            {
                g.AddEdge(dgNoCycle[i][0], dgNoCycle[i][1]);
            }
            DirectedShortestPath shortestPath = new DirectedShortestPath(g, 0);
            // 0 -> 6 -> 9 -> 12
            int[] path = {0, 6, 9, 12};
            int ctr = 0;
            foreach (var v in shortestPath.PathTo(12))
            {
                Assert.AreEqual(path[ctr++], v);
            }
        }
    }
}
